package components

import (
	"web/actions"
	"web/api"
	"web/store"
	"strings"
	"github.com/wuhuang26/locstor"
	v "github.com/gopherjs/vecty"
	"github.com/gopherjs/vecty/elem"
	"github.com/gopherjs/vecty/event"
	"github.com/gopherjs/vecty/prop"
)

type LoginForm struct {
	v.Core
	Username           string `vecty:"prop"`
	UsernameInvalidMsg string `vecty:"prop"`
	Password           string `vecty:"prop"`
	PasswordInvalidMsg string `vecty:"prop"`
	Validated          bool   `vecty:"prop"`
}

func (lf *LoginForm) checkUsername() bool {
	name := strings.TrimSpace(lf.Username)
	lf.UsernameInvalidMsg = ""
	if name == "" {
		lf.UsernameInvalidMsg = "用户名不能为空"
		return false
	}
	return true
}

func (lf *LoginForm) checkPassword() bool {
	lf.PasswordInvalidMsg = ""
	if lf.Password == "" {
		lf.PasswordInvalidMsg = "密码不能为空"
		return false
	}
	return true
}

func (lf *LoginForm) CheckValidity() bool {
	lf.Validated = true
	if !lf.checkUsername() {
		return false
	}
	if !lf.checkPassword() {
		return false
	}
	return true
}

func (lf *LoginForm) onUsernameChange(e *v.Event) {
	username := strings.TrimSpace(e.Target.Get("value").String())
	store.Get().Dispatch(&actions.SetUsername{
		Username: username,
	})

	err := locstor.SetItem("username", username)
	if err != nil {
		println(err.Error())
		return
	}
}

func needValidationFormControl(validated bool, invalidMsg string) v.Applyer {
	return v.Markup(
		v.Class("form-control"),
		v.MarkupIf(validated && invalidMsg != "",
			v.Class("is-invalid")),
		v.MarkupIf(validated && invalidMsg == "",
			v.Class("is-valid")),
	)
}

func (lf *LoginForm) Render() v.ComponentOrHTML {
	return elem.Form(
		elem.Div(
			v.Markup(
				v.Class("field"),
			),

			elem.Label(
				v.Markup(
					v.Class("label"),
					v.Attribute("for", "login-edit-username"),
				),
				v.Text("用户名:"),
			),

			elem.Div(
				v.Markup(
					v.Class("control", "has-icons-left"),
				),

				elem.Input(
					v.Markup(
						needValidationFormControl(lf.Validated, lf.UsernameInvalidMsg),
						prop.Type(prop.TypeText),
						v.Class("input"),
						prop.ID("login-edit-username"),
						prop.Value(lf.Username),
						event.Change(lf.onUsernameChange),
						event.Input(func(e *v.Event) {
							value := e.Target.Get("value").String()
							lf.Username = value
							lf.checkUsername()
							v.Rerender(lf)
						}),
					),
				),

				elem.Span( // user icon
					v.Markup(
						v.Class("icon", "is-small", "is-left"),
					),
					elem.Italic(
						v.Markup(
							v.Class("fas", "fa-user"),
						),
					),
				),
			),

			elem.Paragraph(
				v.Markup(
					v.Class("help"),
				),

				v.Text(lf.UsernameInvalidMsg),
			),
		),

		elem.Div(
			v.Markup(
				v.Class("field"),
			),
			elem.Label(
				v.Markup(
					v.Class("label"),
					v.Attribute("for", "login-edit-password"),
				),
				v.Text("密码:"),
			),
			elem.Div(
				v.Markup(
					v.Class("control", "has-icons-left"),
				),

				elem.Input(
					v.Markup(
						v.Class("input"),
						needValidationFormControl(lf.Validated, lf.PasswordInvalidMsg),
						prop.Type(prop.TypePassword),
						prop.ID("login-edit-password"),
						prop.Value(lf.Password),
						event.Input(func(e *v.Event) {
							value := e.Target.Get("value").String()
							lf.Password = value
							lf.checkPassword()
							v.Rerender(lf)
						}),
					),
				),

				elem.Span( // lock icon
					v.Markup(
						v.Class("icon", "is-small", "is-left"),
					),
					elem.Italic(
						v.Markup(
							v.Class("fas", "fa-lock"),
						),
					),
				),
			),

			elem.Paragraph(
				v.Markup(
					v.Class("help"),
				),
				v.Text(lf.PasswordInvalidMsg),
			),
		),
	)
}

func (lf *LoginForm) GetValue() *api.AuthInfo {
	return &api.AuthInfo{
		Username: strings.TrimSpace(lf.Username),
		Password: lf.Password,
	}
}
